home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 5757 < prev    next >
Encoding:
Text File  |  1996-08-05  |  2.3 KB  |  77 lines

  1. Newsgroups: comp.lang.c
  2. Path: thinkage.on.ca!atbowler
  3. From: atbowler@thinkage.on.ca (Alan Bowler)
  4. Subject: Re: Pre-processing:  Can this be done?
  5. Message-ID: <Dn3n9K.LCu@thinkage.on.ca>
  6. Sender: news@thinkage.on.ca
  7. Organization: Thinkage Ltd.
  8. References: <DMGo4t.7r7@gti-ia.nl> <4fe164$nmg@news.cencom.net>
  9. Date: Wed, 21 Feb 1996 00:12:55 GMT
  10.  
  11. In article <4fe164$nmg@news.cencom.net> tanp@ns (Bill Wendling) writes:
  12. >Paul Wallis inexplicably wrote:
  13. >} Hi all,
  14. >
  15. >} I'm trying to write a function which will print trace statements.
  16. >} I want the file and line to be added to the argument list
  17. >} automatically.  I am, however, having some problems working
  18. >} my way around the pre-processor. I would like to be able to enter
  19. >} the following line:
  20. >
  21. >}     trace("%d, %f", an_int, a_float);
  22. >
  23. >} and have the arguments passed as so:
  24. >
  25. >}     _trace(__FILE__, __LINE__, "%d, %f", an_int, a_float);
  26. >
  27. >} I have defined a macro trace so:
  28. >
  29. >}     #define trace(x) _trace(__FILE__, __LINE__, x)
  30. >
  31. >Try
  32. >
  33. >#define trace(x, y, z) _trace(__FILE__, __LINE__, x, y, z)
  34. >
  35. >You have 3 parms, not one.
  36. >
  37. I think that he wants to pass a variable number of arguments.
  38. You can't define such macro with standard C although some compilers
  39. do allow an extension.
  40.  
  41. You can however get someting *almost* as good with a standard
  42. preprocessor.
  43.  
  44. The first cut at doing this is something like the following:
  45.  
  46. #define trace mytrace(__FILE__, __LINE,   /* Note the unpaired ( */
  47.  
  48. later on to use it you could code
  49.  
  50.   trace "%d, %f", an_int, a_float);       /* close the function here */
  51.  
  52. This is ugly because of the unpaired () in the source, but more so 
  53. because you can't easily remove the trace by changing the macro.
  54.  
  55. The second cut splits the trace into two calls.
  56.  
  57. extern void tracehead(const char *srcfile, int srcline);
  58. extern void traceinfo(const char *fmt, ...);
  59.  
  60. #define trace(args) {                             \
  61.       tracehead(__FILE__, __LINE);                \
  62.       traceinfo args ;        /* Note no () */      \
  63.   }
  64.  
  65. Later to use the trace call, you code
  66.  
  67.     trace((    "%d, %f", an_int, a_float));
  68.  
  69. The double (( and )) is only mildly ugly, but serves to reduce the
  70. full list to a single macro argument.  You can then define away
  71. the trace calls with
  72.  
  73. #define trace(args) /* Nothing */
  74.  
  75. If you really don't like the (( )) solution you can define a
  76. series of macros.  trace1(fmt)  trace2(fmt,a1), trace3(fmt,a1,a2) ...
  77.